﻿@using Resource;
@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no" />
    <meta http-equiv="Expires" content="0">
    <meta http-equiv="Pragma" content="no-cache">
    <meta http-equiv="Cache-control" content="no-cache">
    <meta http-equiv="Cache" content="no-cache">
    <link rel="shortcut icon" type="image/x-icon" href="/images/favicon_title.ico?v=@DateTime.Now.Ticks" />
    @{
        await Html.RenderPartialAsync("/Views/Shared/_LayoutScript.cshtml");
    }

    <title>FYOEE</title>
    <style type="text/css" href="?v=@DateTime.Now.Ticks">
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        html, body {
            height: 100%;
            font-family: "Microsoft YaHei", sans-serif;
            background: #f2f2f2;
        }

        /* scrollbar Chrome / Edge / Safari */
        ::-webkit-scrollbar {
            width: 6px;
            height: 6px;
        }

        ::-webkit-scrollbar-track {
            background: transparent;
        }

        ::-webkit-scrollbar-thumb {
            background: rgba(0,0,0,0.2);
            border-radius: 3px;
        }

        ::-webkit-scrollbar-thumb:hover {
            background: rgba(0,0,0,0.3);
        }

        /* Firefox（全局） */
        * {
            scrollbar-width: thin;
            scrollbar-color: rgba(0,0,0,0.2) transparent;
        }
        /* crollbar */

        /*下拉框*/
        .accordion select {
            padding-left: 4px;
            padding-right: 4px;
            border-radius: 6px;
            border: 1px solid #ccc;
            outline: none;
            transition: border-color 0.2s ease;
        }

        .accordion select:focus {
            border-color: #4d90fe;
        }

        .accordion select option:hover {
            background-color: #e6f0ff;
        }

        .accordion select option:checked {
            background-color: #4d90fe;
            color: #fff;
        }
        /*end下拉框*/
        

        .dashboard {
            display: flex;
            height: 100vh;
        }

        .sidebar {
            width: 12vw;
            min-width: 180px;
            background: #e9eef4;
            padding: 10px;
            overflow-y: auto;
            transition: all 0.3s ease;
        }

        .sidebar.hidden {
            display: none;
        }

        /* Accordion Styles */
        .accordiont {
            font-size: 14px;
            height: 30px;
            line-height: 30px;
            background-color: #15478d;
            border-radius: 5px;
            color: white;
            text-align: center;
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        .accordion .accordion-header {
            font-size: 12px;
            margin: 6px 0;
            cursor: pointer;
            background-color: #d6dee8;
            padding: 6px;
            border-radius: 4px;
        }

        .accordion .accordion-body {
            max-height: 0;
            overflow: hidden;
            transition: max-height 0.3s ease;
        }

        .accordion .accordion-body select {
            width: 100%;
        }

        .accordion-item.active .accordion-body {
            max-height: 100%;
        }

        #selectYear {
            height: 3vh;
        }

        #selectQuarter {
            height: 9.2vh;
        }

        #selectMonth {
            height: 26.7vh;
        }

        #selectWeek,
        #selectReason {
            height: 64.5vh;
        }

        .main {
            flex: 1;
            display: flex;
            flex-direction: column;
            transition: all 0.3s ease;
            overflow: hidden; 
            padding: 0px 10px;
        }

        .header {
            position: sticky;
            top: 0;
            z-index: 100;
            background: #15478d;
            color: white;
            height: 50px;
            display: flex;
            align-items: center;
            justify-content: center; 
            font-size: 25px;
            font-weight: bold;
            margin: -10px;
            line-height: 50px;
            margin-bottom: 10px;
            padding-left: 10px;
        }

        .toggle-sidebar-btn {
            color: white;
            border: none;
            font-size: 25px;
            font-weight: normal;
            border-radius: 4px;
            cursor: pointer;
            position: absolute;
            left: 10px;
        }

        .kpi-bar {
            position: sticky;
            top: 50px;
            z-index: 99;
            background: #f2f2f2;
            display: flex;
            gap: 10px;
            padding: 10px 0px;
        }

        .kpi {
            flex: 1;
            border-radius: 12px;
            padding: 12px;
            text-align: center;
            box-shadow: 0 4px 2px rgba(0,0,0,0.1);
            color: white;
            font-weight: bold;
        }

        .kpi-title {
            text-align: left;
            font-size: 14px;
        }

        .kpi-value {
            font-size: 22px;
            margin-top: 5px;
        }

        .green {
            background-color: #a3d49c;
        }

        .orange {
            background-color: #f5b183;
        }

        .blue {
            background-color: #01a8f2;
        }

        .purple {
            background-color: #a69ddc;
        }

        .yellow {
            background-color: #eeb900;
        }

        .cyan {
            background-color: #00d2e8;
        }

        .content-scroll {
            flex: 1;
            overflow: auto;
            width: 100%;
        }

        .chart-grid {
            display: grid;
            grid-template-columns: repeat(4, 498px);
            gap: 10px;
            grid-auto-rows: 30vh;
            min-width: max-content;
        }

        .chart-box {
            background: white;
            border-radius: 6px;
            padding: 5px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.08);
            display: flex;
        }

        .span-2 {
            grid-column: span 2;
        }

        .span-3 {
            grid-column: span 3;
        }

        .span-4 {
            grid-column: span 4;
        }

        .span-5 {
            grid-column: span 5;
        }

    </style>
</head>
<body>
    <div class="dashboard" id="capture">
        <div class="sidebar" id="sidebar">
            <div class="toggleSidebar accordiont">≡ 筛选条件</div>
            <div class="accordion">
                <div class="accordion-item">
                    <h4 class="accordion-header">财务年度</h4>
                    <div class="accordion-body">
                        <select id="selectYear"></select>
                    </div>
                </div>
                <div class="accordion-item">
                    <h4 class="accordion-header">财务季度</h4>
                    <div class="accordion-body">
                        <select id="selectQuarter" multiple></select>
                    </div>
                </div>
                <div class="accordion-item">
                    <h4 class="accordion-header">财务月份</h4>
                    <div class="accordion-body">
                        <select id="selectMonth" multiple></select>
                    </div>
                </div>
                <div class="accordion-item">
                    <h4 class="accordion-header">财务周数</h4>
                    <div class="accordion-body">
                        <select id="selectWeek" multiple></select>
                    </div>
                </div>
                <div class="accordion-item">
                    <h4 class="accordion-header">故障原因</h4>
                    <div class="accordion-body">
                        <select id="selectReason" multiple></select>
                    </div>
                </div>
            </div>
        </div>

        <div class="main">
            <div class="header">
                @* <button id="save">保存为图片</button> *@
                <div class="toggleSidebar toggle-sidebar-btn">≡</div>OEE仪表盘
            </div>
            <div class="kpi-bar">
                <div class="kpi green"><div class="kpi-title">Input</div><div class="kpi-value">0</div></div>
                <div class="kpi orange"><div class="kpi-title">Output</div><div class="kpi-value">0</div></div>
                <div class="kpi blue"><div class="kpi-title">Yield良率</div><div class="kpi-value">0</div></div>
                <div class="kpi purple"><div class="kpi-title">时间稼动率</div><div class="kpi-value">0</div></div>
                <div class="kpi yellow"><div class="kpi-title">效率稼动率</div><div class="kpi-value">0</div></div>
                <div class="kpi cyan"><div class="kpi-title">OEE</div><div class="kpi-value">0</div></div>
            </div>
            <div class="content-scroll">
                <div class="chart-grid">
                    <div id="chart1" class="chart-box">1</div>
                    <div id="chart2" class="chart-box">2</div>
                    <div id="chart3" class="chart-box">3</div>
                    <div id="chart4" class="chart-box">4</div>
                    <div id="chart5" class="chart-box">5</div>
                    <div id="chart6" class="chart-box">6</div>
                    <div id="chart7" class="chart-box">7</div>
                    <div id="chart8" class="chart-box">8</div>
                    <div id="chart9" class="chart-box">9</div>
                    <div id="chart10" class="chart-box">10</div>
                    <div id="chart11" class="chart-box">11</div>
                    <div id="chart12" class="chart-box">12</div>
                    <div id="chart13" class="chart-box span-4">13</div>
                    <div id="chart14" class="chart-box span-4">14</div>
                </div>
            </div>
        </div>
    </div>

    <script type="text/javascript" href="?v=@DateTime.Now.Ticks">
        $('.toggleSidebar').on('click', function () {
            $('#sidebar').toggleClass('hidden');
        });

        @*
        //一次展开一个
        $('.accordion-header').on('click', function () {
            const $item = $(this).parent();
            const isActive = $item.hasClass('active');
            $('.accordion-item').removeClass('active');
            if (!isActive) {
                $item.addClass('active');
            }
        });
        *@

        //多个展开
        $('.accordion-header').on('click', function () {
            $(this).parent().toggleClass('active');
        });

        $(function () {
          //全局数据变量
          let oeeData = null;
          //自动全选
          function renderOptions($select, items, valueField = 'value', textField = 'text') {
              if (!Array.isArray(items) || items.length === 0) {
                  $select.empty().trigger('change');
                  return;
              }
              $select.empty();
              const filteredItems = items.filter(item =>
                  item[valueField] !== null && item[valueField] !== "NULL"
              );
              if (filteredItems.length === 0) {
                  $select.trigger('change'); 
                  return;
              }
              $.each(filteredItems, (_, item) => {
                  $select.append(`<option value="${item[valueField]}">${item[textField]}</option>`);
              });
              const allValues = filteredItems.map(i => i[valueField]);
              $select.val(allValues).trigger('change');
          }

          //加载数据
          $.ajax({
            type: "POST",
            url: api + "/ReportAction/GetFYOEEReportComBox",
            dataType: "json",
            success: function (res) {
              oeeData = res.ReturnData;
              if (!oeeData) return;

              //初始化年（单选，默认第一项）
              const years = oeeData.year || [];
              const $year = $('#selectYear');
              $year.empty();
              $.each(years, (_, y) => {
                $year.append(`<option value="${y.value}">${y.text}</option>`);
              });
              const defaultYear = years[0]?.value;
              $year.val(defaultYear).trigger('change');
            },
            error: () => alert("加载失败")
          });

          // 年 → 季度
          $('#selectYear').on('change', function () {
            const year = $(this).val();
            const quarters = oeeData.quarter.filter(q => q.year === year);
            renderOptions($('#selectQuarter'), quarters);
          });

          // 季度 → 月
          $('#selectQuarter').on('change', function () {
            const year = $('#selectYear').val();
            const quarters = $('#selectQuarter').val();
            const months = oeeData.month.filter(m =>
              m.year === year && quarters.includes(m.quarter)
            );
            renderOptions($('#selectMonth'), months);
          });

          // 月 → 周
          $('#selectMonth').on('change', function () {
            const year = $('#selectYear').val();
            const quarters = $('#selectQuarter').val();
            const months = $('#selectMonth').val();
            const weeks = oeeData.week.filter(w =>
              w.year === year &&
              quarters.includes(w.quarter) &&
              months.includes(w.month)
            );
            renderOptions($('#selectWeek'), weeks);
          });

          // 周 → 原因
          $('#selectWeek').on('change', function () {
            const year = $('#selectYear').val();
            const quarters = $('#selectQuarter').val();
            const months = $('#selectMonth').val();
            const weeks = $('#selectWeek').val();
            const reasons = oeeData.reason.filter(r =>
                r.year === year &&
                quarters.includes(r.quarter) &&
                months.includes(r.month) &&
                weeks.includes(r.week)
            );
            renderOptions($('#selectReason'), reasons);
          });
        });

    </script>

    <script type="text/javascript" href="?v=@DateTime.Now.Ticks">
        function disposeAndResizeCharts(selector = '.chart-box') {
            $(selector).each(function () {
                const dom = this;
                const chart = echarts.getInstanceByDom(dom);
                if (chart) {
                    chart.dispose();
                }
                const newChart = echarts.init(dom);
                newChart.resize();
            });
        }

        function loadDataAndInit() {
            const header_key = {
                year: $("#selectYear").val(),
                quarters: $("#selectQuarter").val(),
                months: $("#selectMonth").val(),
                weeks: $("#selectWeek").val()
            };
            var pam = {};
            pam.header_key = JSON.stringify(header_key);
            $.ajax({
                type: "POST",
                url: api + "/ReportAction/GetFYOEEReport",
                data: pam,
                dataType: "json",
                success: function (res) {
                    const result = res.ReturnData;
                    disposeAndResizeCharts();
                    lazyRenderCharts(result);
                },
                error: function (err) {
                    console.error("数据加载失败：", err);
                }
            });
        }

        let loadTimer = null;
        $('.accordion select').on('change', function () {
            clearTimeout(loadTimer);
            loadTimer = setTimeout(() => {
                loadDataAndInit();
            }, 300); 
        });

        //调度懒加载
        function lazyRenderCharts(data) {
            const chartQueue = [
                //FQ
                { fn: fqOeeChart, delay: 0 },
                { fn: fqDowntimeChart, delay: 0 },
                { fn: fqAssyChart, delay: 0 },
                //Monthly
                { fn: monthlyOeeChart, delay: 300 },
                { fn: monthlyDowntimeChart, delay: 300 },
                { fn: monthlyAssyChart, delay: 300 },
                //Week
                { fn: weekOeeChart, delay: 600 },
                { fn: weekDowntimeChart, delay: 600 },
                { fn: weekAssyChart, delay: 600 },
                //Daily
                { fn: dailyOeeChart, delay: 900 }
            ];
            const idle = window.requestIdleCallback || function (cb) { setTimeout(cb, 200); };
            chartQueue.forEach(({ fn, delay }) => {
                setTimeout(() => {
                    idle(() => {
                        try {
                            fn(data);
                        } catch (e) {
                            console.warn('图表渲染失败：', fn.name, e);
                        }
                    });
                }, delay);
            });
        }

        /*** FQ ***/
        //FQ OEE
        function fqOeeChart(data) {
            const selectedYear = $("#selectYear").val();        
            const selectedQuarters = $("#selectQuarter").val();  
            const datafilter = data.filter(d =>
                d.DATA_TYPE === "OEE" &&
                d.CL_TYPE === "FQ" &&
                d.FISCAL_YEAR === selectedYear &&
                selectedQuarters.includes(d.FISCAL_QUARTER)
            );
            const groupMap = {};
            const dateSet = new Set();
            datafilter.forEach(d => {
                const key = d.WORK_CLASS + d.TYPE;
                dateSet.add(d.DATE);
                if (!groupMap[key]) groupMap[key] = {};
                if (!groupMap[key][d.DATE]) groupMap[key][d.DATE] = [];
                groupMap[key][d.DATE].push(d.OEE);
            });
            const xAxis = Array.from(dateSet).sort();
            const series = Object.entries(groupMap).map(([legend, values]) => ({
                name: legend,
                type: 'line',
                smooth: true,
                data: xAxis.map(date => {
                    const list = values[date] || [];
                    const avg = list.length ? list.reduce((a, b) => a + b, 0) / list.length : 0;
                    return +(avg * 100).toFixed(1);
                })
            }));
            const chartDom = document.getElementById('chart1');
            const myChart = echarts.init(chartDom);
            const option = {
                title: {
                    text: 'FQ OEE',
                    left: 'left', 
                    textStyle: {
                        fontSize: 12,
                        fontWeight: 'bold'
                    }
                },
                tooltip: {
                    trigger: 'axis',
                    valueFormatter: function (value) {
                        return (value === null || value === undefined) ? '-' : value + '%';
                    }
                },
                legend: {
                    data: Object.keys(groupMap),
                    top: 20, 
                    itemWidth: 10,     
                    itemHeight: 10,   
                    textStyle: {
                        fontSize: 10    
                    }
                },
                xAxis: { type: 'category', data: xAxis,axisLabel: {fontSize: 10}},
                yAxis: {
                    type: 'value',
                    axisLabel: { formatter: '{value}%' },
                },
                grid: { left: '1%', right: '1%', bottom: '1%', containLabel: true },
                series
            };
            myChart.setOption(option);
            window.addEventListener('resize', () => {
                myChart.resize();
            });
            fqOutputYieldChart(datafilter);
        }

        //FQ Output
        function fqOutputYieldChart(data) {
            const summary = {};  
            data.forEach(d => {
                if (!summary[d.DATE]) summary[d.DATE] = {};
                if (!summary[d.DATE][d.TYPE]) {
                    summary[d.DATE][d.TYPE] = { input: 0, output: 0 };
                }

                summary[d.DATE][d.TYPE].input += d.SUM_INPUT_QTY;
                summary[d.DATE][d.TYPE].output += d.SUM_OUTPUT_QTY;
            });
            const xAxis = Object.keys(summary).sort();
            const aaInput = xAxis.map(date => summary[date].AA?.input || 0);
            const aaOutput = xAxis.map(date => summary[date].AA?.output || 0);
            const aaYield = xAxis.map(date => {
                const d = summary[date].AA;
                return d && d.input > 0 ? +(d.output / d.input * 100).toFixed(1) : 0;
            });
            const testInput = xAxis.map(date => summary[date].TEST?.input || 0);
            const testOutput = xAxis.map(date => summary[date].TEST?.output || 0);
            const testYield = xAxis.map(date => {
                const d = summary[date].TEST;
                return d && d.input > 0 ? +(d.output / d.input * 100).toFixed(1) : 0;
            });
            const chart = echarts.init(document.getElementById('chart2'));
            chart.setOption({
                title: {
                    text: 'FQ Output',
                    left: 'left',
                    textStyle: { fontSize: 12, fontWeight: 'bold' }
                },
                tooltip: {
                    trigger: 'axis',
                    formatter: params =>
                        params[0].axisValue + '<br/>' +
                        params.map(p =>
                            `${p.marker}${p.seriesName}: ` +
                            (p.value == null ? '-' : p.seriesName.includes('Yield') ? p.value + '%' : p.value)
                        ).join('<br/>')
                },
                legend: {
                    top: 20,
                    itemWidth: 10,
                    itemHeight: 10,
                    textStyle: { fontSize: 10 },
                    data: ['AA Input', 'AA Output', 'AA Yield', 'TEST Input', 'TEST Output', 'TEST Yield']
                },
                grid: { left: '1%', right: '1%', bottom: '1%', containLabel: true },
                xAxis: { type: 'category', data: xAxis,axisLabel: {fontSize: 10} },
                yAxis: [
                  {
                    type: 'value',
                    alignTicks: true,
                    axisLabel: {
                      formatter: function (value) {
                        if (value >= 1000) {
                          return (value / 1000) + 'k';
                        }
                        return value;
                      }
                    }
                  },
                  {
                    type: 'value',
                    alignTicks: true,
                    axisLabel: {
                      formatter: '{value}%' 
                    }
                  }
                ],
                series: [
                    { name: 'AA Input', type: 'bar', barGap: 0,barCategoryGap: "40%",data: aaInput },
                    { name: 'AA Output', type: 'bar',barGap: 0,barCategoryGap: "40%", data: aaOutput },
                    { name: 'AA Yield', type: 'line', yAxisIndex: 1, data: aaYield },
                    { name: 'TEST Input', type: 'bar', barGap: 0,barCategoryGap: "40%", data: testInput },
                    { name: 'TEST Output', type: 'bar', barGap: 0,barCategoryGap: "40%", data: testOutput },
                    { name: 'TEST Yield', type: 'line', yAxisIndex: 1, data: testYield }
                ]
            });
            window.addEventListener('resize', () => chart.resize());
        }

        //FQ Downtime
        function fqDowntimeChart(data) {
            const selectedYear = $("#selectYear").val();
            const selectedQuarters = $("#selectQuarter").val();
            const datafilter = data.filter(d =>
                d.DATA_TYPE === "EMS" &&
                d.CL_TYPE === "Daily" &&
                d.FISCAL_YEAR === selectedYear &&
                selectedQuarters.includes(d.FISCAL_QUARTER)
            );
            const groupMap = {};
            datafilter.forEach(d => {
                const date = d.FISCAL_QUARTER;
                const key = `${d.WORK_CLASS}-${d.TYPE}`;
                const val = parseFloat(d.DOWNTIME_RATE_PERCENT) * 100;
                if (!groupMap[date]) {
                    groupMap[date] = {
                        "白班-ASSY": [],
                        "白班-TEST": [],
                        "晚班-ASSY": [],
                        "晚班-TEST": []
                    };
                }
                if (groupMap[date][key]) {
                    groupMap[date][key].push(val);
                }
            });

            //构建图表数据
            const dates = Object.keys(groupMap).sort(); 
            const legend = ["白班-ASSY", "白班-TEST", "晚班-ASSY", "晚班-TEST"];
            const series = legend.map(legendKey => {
                return {
                    name: legendKey,
                    type: 'bar',
                    barGap: 0,
                    barCategoryGap: "40%",
                    data: dates.map(date => {
                        const arr = groupMap[date][legendKey] || [];
                        if (arr.length === 0) return 0;
                        return (arr.reduce((a, b) => a + b, 0) / arr.length).toFixed(2);
                    })
                };
            });

            const option = {
                title: {
                    text: 'FQ Downtime',
                    left: 'left',
                    textStyle: { fontSize: 12, fontWeight: 'bold' }
                },
                tooltip: {
                    trigger: 'axis',
                    valueFormatter: function (value) {
                        return (value === null || value === undefined) ? '-' : value + '%';
                    }
                },
                legend: { top: 20,itemWidth: 10,itemHeight: 10,textStyle: { fontSize: 10 },data: legend},
                grid: { left: '1%', right: '1%', bottom: '1%', containLabel: true },
                xAxis: {
                    type: 'category',
                    data: dates,
                    axisLabel: {fontSize: 10}
                },
                yAxis: {
                    type: 'value',
                    axisLabel: { formatter: '{value}%' }
                },
                series
            };
            const chart = echarts.init(document.getElementById("chart3")); 
            chart.setOption(option);
            window.addEventListener('resize', () => chart.resize());
        }

        //FQ Assy& Test
        function fqAssyChart(data) {
            const selectedYear = $("#selectYear").val();
            const selectedQuarters = $("#selectQuarter").val();
            const selectReasons = $("#selectReason").val();
            const datafilter = data.filter(d =>
                d.DATA_TYPE === "EMS" &&
                d.CL_TYPE === "Daily" &&
                d.FISCAL_YEAR === selectedYear &&
                selectedQuarters.includes(d.FISCAL_QUARTER) &&
                selectReasons.includes(d.REASON)
            );
            //分组 TYPE + REASON
            const grouped = {};
            datafilter.forEach(item => {
                const { TYPE, REASON, DOWNTIME_RATE_PERCENT } = item;
                if (!grouped[REASON]) grouped[REASON] = { ASSY: [], TEST: [] };
                grouped[REASON][TYPE].push(DOWNTIME_RATE_PERCENT);
            });

            //平均值 + 汇总总值
            const reasonStats = Object.entries(grouped).map(([reason, types]) => {
                const assyAvg = types.ASSY.length ? types.ASSY.reduce((a, b) => a + b) / types.ASSY.length : 0;
                const testAvg = types.TEST.length ? types.TEST.reduce((a, b) => a + b) / types.TEST.length : 0;
                return {
                    reason,
                    assy: +(assyAvg * 100).toFixed(2),
                    test: +(testAvg * 100).toFixed(2),
                    total: +(assyAvg + testAvg) * 100
                };
            });

            //按 total 降序
            reasonStats.sort((a, b) => b.total - a.total);

            const xAxisData = reasonStats.map(r => r.reason);
            const assyData = reasonStats.map(r => r.assy);
            const testData = reasonStats.map(r => r.test);

            //累计百分比数据
            const cumulative = [];
            let sum = 0;
            const totalSum = reasonStats.reduce((acc, cur) => acc + cur.total, 0);
            reasonStats.forEach(r => {
                sum += r.total;
                cumulative.push(+(sum / totalSum * 100).toFixed(2));
            });
            const seriesData = [
                {
                    name: 'ASSY',
                    type: 'bar',
                    stack: 'total',
                    data: assyData
                },
                {
                    name: 'TEST',
                    type: 'bar',
                    stack: 'total',
                    data: testData
                },
                {
                    name: '累计百分比',
                    type: 'line',
                    yAxisIndex: 1,
                    smooth: true,
                    symbol: 'circle',
                    symbolSize: 6,
                    lineStyle: { color: 'orange' },
                    itemStyle: { color: 'orange' },
                    data: cumulative
                }
            ];

            //绘制图表
            function renderParetoChart(xAxisData, seriesData) {
                const chart = echarts.init(document.getElementById('chart4'));
                const option = {
                    title: {
                        text: 'FQ Reason',
                        left: 'left',
                        textStyle: { fontSize: 12, fontWeight: 'bold' }
                    },
                    tooltip: {
                        trigger: 'axis',
                        valueFormatter: function (value) {
                            return (value === null || value === undefined) ? '-' : value + '%';
                        }
                    },
                    legend: {
                        top: 20,
                        itemWidth: 10,
                        itemHeight: 10,
                        textStyle: { fontSize: 10 },
                        data: ['ASSY', 'TEST', '累计百分比']
                    },
                    grid: { left: '1%', right: '1%', bottom: '1%', containLabel: true },
                    xAxis: {
                        type: 'category',
                        data: xAxisData,
                        axisLabel: {
                            rotate: 45,
                            fontSize: 10,
                            formatter: value => value.length > 10 ? value.slice(0, 10) + '…' : value
                        }
                    },
                    yAxis: [
                        {
                            type: 'value',
                            alignTicks: true,
                            axisLabel: { formatter: '{value}%' }
                        },
                        {
                            type: 'value',
                            alignTicks: true,
                            axisLabel: { formatter: '{value}%' }
                        }
                    ],
                    series: seriesData
                };
                chart.setOption(option);
                window.addEventListener('resize', () => chart.resize());
            }
            renderParetoChart(xAxisData, seriesData);
        }

        /*** Monthly ***/
        //Monthly OEE
        function monthlyOeeChart(data) {
            const selectedYear = $("#selectYear").val();
            const selectedQuarters = $("#selectQuarter").val();
            const selectMonths = $("#selectMonth").val();

            const datafilter = data.filter(d =>
                d.DATA_TYPE === "OEE" &&
                d.CL_TYPE === "Month" &&
                d.FISCAL_YEAR === selectedYear &&
                selectedQuarters.includes(d.FISCAL_QUARTER) &&
                selectMonths.includes(d.FISCAL_MONTH_NUM)
            );
            const monthOrder = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
            //去重 DATE 字段
            const dateMap = {};
            for (let i = 0; i < datafilter.length; i++) {
                const month = datafilter[i].DATE;
                if (!dateMap[month]) {
                    dateMap[month] = true;
                }
            }
            //排序
            const xAxisData = Object.keys(dateMap).sort((a, b) => monthOrder.indexOf(a) - monthOrder.indexOf(b));
            const groupMap = {
                "白班 AA": [],
                "白班 TEST": [],
                "晚班 AA": [],
                "晚班 TEST": []
            };

            xAxisData.forEach(month => {
                const itemsInMonth = datafilter.filter(d => d.DATE === month);
                groupMap["白班 AA"].push(getOeePercent(itemsInMonth, "白班", "AA"));
                groupMap["白班 TEST"].push(getOeePercent(itemsInMonth, "白班", "TEST"));
                groupMap["晚班 AA"].push(getOeePercent(itemsInMonth, "晚班", "AA"));
                groupMap["晚班 TEST"].push(getOeePercent(itemsInMonth, "晚班", "TEST"));
            });

            const seriesData = Object.keys(groupMap).map(key => ({
                name: key,
                type: 'line',
                smooth: true,
                symbol: 'circle',
                symbolSize: 6,
                data: groupMap[key]
            }));
            renderOeeLineChart(xAxisData, seriesData);

            //获取某类数据的OEE百分比
            function getOeePercent(dataList, workClass, type) {
                const target = dataList.find(d => d.WORK_CLASS === workClass && d.TYPE === type);
                return target ? +(target.OEE * 100).toFixed(2) : null;
            }

            //渲染折线图
            function renderOeeLineChart(xAxisData, seriesData) {
                const chart = echarts.init(document.getElementById('chart5'));
                const option = {
                    title: {
                        text: 'Monthly OEE',
                        left: 'left',
                        textStyle: { fontSize: 12, fontWeight: 'bold' }
                    },
                    tooltip: {
                        trigger: 'axis',
                        valueFormatter: function (value) {
                            return (value === null || value === undefined) ? '-' : value + '%';
                        }
                    },
                    legend: {
                        top: 20,
                        itemWidth: 10,
                        itemHeight: 10,
                        textStyle: { fontSize: 10 }
                    },
                    grid: { left: '1%', right: '1%', bottom: '1%', containLabel: true },
                    xAxis: {
                        type: 'category',
                        data: xAxisData,
                        axisLabel: {
                            rotate: 0,
                            fontSize: 10
                        }
                    },
                    yAxis: {
                        type: 'value',
                        axisLabel: {
                            formatter: '{value}%'
                        }
                    },
                    series: seriesData
                };
                chart.setOption(option);
                window.addEventListener('resize', () => chart.resize());
            }
            monthlyOutputChart(datafilter);
        }

        //Monthly Output
        function monthlyOutputChart(datafilter) {
            const monthOrder = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
            //去重并排序月份
            const monthMap = {};
            datafilter.forEach(d => monthMap[d.DATE] = true);
            const xAxisData = Object.keys(monthMap).sort((a, b) => monthOrder.indexOf(a) - monthOrder.indexOf(b));

            //构建每月 AA 和 TEST 汇总
            const resultMap = {};
            xAxisData.forEach(month => {
                const rows = datafilter.filter(d => d.DATE === month);
                resultMap[month] = {
                    AA: { input: 0, output: 0 },
                    TEST: { input: 0, output: 0 }
                };
                rows.forEach(r => {
                    if (r.TYPE === "AA") {
                        resultMap[month].AA.input += r.SUM_INPUT_QTY;
                        resultMap[month].AA.output += r.SUM_OUTPUT_QTY;
                    } else if (r.TYPE === "TEST") {
                        resultMap[month].TEST.input += r.SUM_INPUT_QTY;
                        resultMap[month].TEST.output += r.SUM_OUTPUT_QTY;
                    }
                });
            });

            //构建系列数据
            const aaInput = [], aaOutput = [], aaYield = [];
            const testInput = [], testOutput = [], testYield = [];

            xAxisData.forEach(month => {
                const aa = resultMap[month].AA;
                const test = resultMap[month].TEST;

                aaInput.push(aa.input);
                aaOutput.push(aa.output);
                aaYield.push(aa.input > 0 ? +(aa.output / aa.input * 100).toFixed(2) : null);

                testInput.push(test.input);
                testOutput.push(test.output);
                testYield.push(test.input > 0 ? +(test.output / test.input * 100).toFixed(2) : null);
            });
            const seriesData = [
                { name: "AA Input", type: "bar", yAxisIndex: 0, barGap: 0,barCategoryGap: "40%",data: aaInput },
                { name: "AA Output", type: "bar", yAxisIndex: 0, barGap: 0,barCategoryGap: "40%", data: aaOutput },
                { name: "AA Yield", type: "line", yAxisIndex: 1, smooth: true, symbol: "circle", data: aaYield },
                { name: "TEST Input", type: "bar", yAxisIndex: 0, barGap: 0,barCategoryGap: "40%",data: testInput },
                { name: "TEST Output", type: "bar", yAxisIndex: 0, barGap: 0,barCategoryGap: "40%",data: testOutput },
                { name: "TEST Yield", type: "line", yAxisIndex: 1, smooth: true, symbol: "circle", data: testYield }
            ];

            renderComboChart(xAxisData, seriesData);
            //渲染图表
            function renderComboChart(xAxisData, seriesData) {
                const chart = echarts.init(document.getElementById('chart6'));
                const option = {
                    title: {
                        text: 'Monthly Output',
                        left: 'left',
                        textStyle: { fontSize: 12, fontWeight: 'bold' }
                    },
                    tooltip: {
                        trigger: 'axis',
                        formatter: params =>
                            params[0].axisValue + '<br/>' +
                            params.map(p =>
                                `${p.marker}${p.seriesName}: ` +
                                (p.value == null ? '-' : p.seriesName.includes('Yield') ? p.value + '%' : p.value)
                            ).join('<br/>')
                    },
                    legend: {
                        top: 20,
                        itemWidth: 10,
                        itemHeight: 10,
                        textStyle: { fontSize: 10 }
                    },
                    grid: { left: '1%', right: '1%', bottom: '1%', containLabel: true },
                    xAxis: {
                        type: 'category',
                        data: xAxisData,
                        axisLabel: {
                            fontSize: 10
                        }
                    },
                    yAxis: [
                      {
                        type: 'value',
                        alignTicks: true,
                        axisLabel: {
                          formatter: function (value) {
                            if (value >= 1000) {
                              return (value / 1000) + 'k';
                            }
                            return value;
                          }
                        }
                      },
                      {
                          type: 'value',
                          alignTicks: true,
                          axisLabel: { formatter: '{value}%' }
                      }
                    ],
                    series: seriesData
                };
                chart.setOption(option);
                window.addEventListener('resize', () => chart.resize());
            }
        }

        //Monthly Downtime
        function monthlyDowntimeChart(data) {
            const selectedYear = $("#selectYear").val();
            const selectedQuarters = $("#selectQuarter").val();
            const selectMonths = $("#selectMonth").val();

            const datafilter = data.filter(d =>
                d.DATA_TYPE === "EMS" &&
                d.CL_TYPE === "Month" &&
                d.FISCAL_YEAR === selectedYear &&
                selectedQuarters.includes(d.FISCAL_QUARTER) &&
                selectMonths.includes(d.FISCAL_MONTH_NUM)
            );

            const monthOrder = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
            const monthSet = {};
            datafilter.forEach(d => monthSet[d.FISCAL_MONTH_NUM] = true);
            const xAxisData = Object.keys(monthSet).sort((a, b) => monthOrder.indexOf(a) - monthOrder.indexOf(b));

            // 初始化 4 组数据结构
            const groups = ["白班 ASSY", "白班 TEST", "晚班 ASSY", "晚班 TEST"];
            const groupMap = {};
            groups.forEach(g => groupMap[g] = []);

            //每月聚合
            xAxisData.forEach(month => {
                const rows = datafilter.filter(d => d.FISCAL_MONTH_NUM === month);
                //分类
                const temp = {
                    "白班 ASSY": [],
                    "白班 TEST": [],
                    "晚班 ASSY": [],
                    "晚班 TEST": []
                };

                rows.forEach(r => {
                    const key = `${r.WORK_CLASS} ${r.TYPE}`;
                    if (temp[key]) temp[key].push(r.DOWNTIME_RATE_PERCENT);
                });

                //平均值
                groups.forEach(g => {
                    const arr = temp[g];
                    const avg = arr.length ? arr.reduce((a, b) => a + b, 0) / arr.length : 0;
                    groupMap[g].push(+(avg * 100).toFixed(2));
                });
            });

            //构建series
            const seriesData = groups.map(name => ({
                name,
                type: 'bar',
                barGap: 0,
                barCategoryGap: "40%",
                data: groupMap[name]
            }));

            renderChart(xAxisData, seriesData);

            //渲染图表
            function renderChart(xAxisData, seriesData) {
                const chart = echarts.init(document.getElementById('chart7'));
                const option = {
                    title: {
                        text: 'Monthly Downtime',
                        left: 'left',
                        textStyle: { fontSize: 12, fontWeight: 'bold' }
                    },
                    tooltip: {
                        trigger: 'axis',
                        valueFormatter: function (value) {
                            return (value === null || value === undefined) ? '-' : value + '%';
                        }
                    },
                    legend: { top: 20,itemWidth: 10,itemHeight: 10,textStyle: { fontSize: 10 },data: groups},
                    grid: { left: '1%', right: '1%', bottom: '1%', containLabel: true },
                    xAxis: {
                        type: 'category',
                        data: xAxisData,
                        axisLabel: { fontSize: 10 }
                    },
                    yAxis: {
                        type: 'value',
     
                        axisLabel: { formatter: '{value}%' }
                    },
                    series: seriesData
                };

                chart.setOption(option);
                window.addEventListener('resize', () => chart.resize());
            }
        }

        //Monthly Assy & Test
        function monthlyAssyChart(data) {
            const selectedYear = $("#selectYear").val();
            const selectedQuarters = $("#selectQuarter").val();
            const selectMonths = $("#selectMonth").val();
            const selectReasons = $("#selectReason").val();
            const datafilter = data.filter(d =>
                d.DATA_TYPE === "EMS" &&
                d.CL_TYPE === "Month" &&
                d.FISCAL_YEAR === selectedYear &&
                selectedQuarters.includes(d.FISCAL_QUARTER) &&
                selectMonths.includes(d.FISCAL_MONTH_NUM) &&
                selectReasons.includes(d.REASON)
            );
            //分组 TYPE + REASON
            const grouped = {};
            datafilter.forEach(item => {
                const { TYPE, REASON, DOWNTIME_RATE_PERCENT } = item;
                if (!grouped[REASON]) grouped[REASON] = { ASSY: [], TEST: [] };
                grouped[REASON][TYPE].push(DOWNTIME_RATE_PERCENT);
            });

            //平均值 + 汇总总值
            const reasonStats = Object.entries(grouped).map(([reason, types]) => {
                const assyAvg = types.ASSY.length ? types.ASSY.reduce((a, b) => a + b) / types.ASSY.length : 0;
                const testAvg = types.TEST.length ? types.TEST.reduce((a, b) => a + b) / types.TEST.length : 0;
                return {
                    reason,
                    assy: +(assyAvg * 100).toFixed(2),
                    test: +(testAvg * 100).toFixed(2),
                    total: +(assyAvg + testAvg) * 100
                };
            });

            //按 total 降序
            reasonStats.sort((a, b) => b.total - a.total);

            const xAxisData = reasonStats.map(r => r.reason);
            const assyData = reasonStats.map(r => r.assy);
            const testData = reasonStats.map(r => r.test);

            //累计百分比数据
            const cumulative = [];
            let sum = 0;
            const totalSum = reasonStats.reduce((acc, cur) => acc + cur.total, 0);
            reasonStats.forEach(r => {
                sum += r.total;
                cumulative.push(+(sum / totalSum * 100).toFixed(2));
            });
            const seriesData = [
                {
                    name: 'ASSY',
                    type: 'bar',
                    stack: 'total',
                    data: assyData
                },
                {
                    name: 'TEST',
                    type: 'bar',
                    stack: 'total',
                    data: testData
                },
                {
                    name: '累计百分比',
                    type: 'line',
                    yAxisIndex: 1,
                    smooth: true,
                    symbol: 'circle',
                    symbolSize: 6,
                    lineStyle: { color: 'orange' },
                    itemStyle: { color: 'orange' },
                    data: cumulative
                }
            ];

            //绘制图表
            function renderParetoChart(xAxisData, seriesData) {
                const chart = echarts.init(document.getElementById('chart8'));
                const option = {
                    title: {
                        text: 'Monthly Reason',
                        left: 'left',
                        textStyle: { fontSize: 12, fontWeight: 'bold' }
                    },
                    tooltip: {
                        trigger: 'axis',
                        valueFormatter: function (value) {
                            return (value === null || value === undefined) ? '-' : value + '%';
                        }
                    },
                    legend: {
                        top: 20,
                        itemWidth: 10,
                        itemHeight: 10,
                        textStyle: { fontSize: 10 },
                        data: ['ASSY', 'TEST', '累计百分比']
                    },
                    grid: { left: '1%', right: '1%', bottom: '1%', containLabel: true },
                    xAxis: {
                        type: 'category',
                        data: xAxisData,
                        axisLabel: {
                            rotate: 45,
                            fontSize: 10,
                            formatter: value => value.length > 10 ? value.slice(0, 10) + '…' : value
                        }
                    },
                    yAxis: [
                        {
                            type: 'value',
                            alignTicks: true,
                            axisLabel: { formatter: '{value}%' }
                        },
                        {
                            type: 'value',
                            alignTicks: true,
                            axisLabel: { formatter: '{value}%' }
                        }
                    ],
                    series: seriesData
                };
                chart.setOption(option);
                window.addEventListener('resize', () => chart.resize());
            }
            renderParetoChart(xAxisData, seriesData);
        }

        /*** Week ***/
        //Week OEE
        function weekOeeChart(data) {
            const selectedYear = $("#selectYear").val();
            const selectedQuarters = $("#selectQuarter").val();
            const selectMonths = $("#selectMonth").val();
            const selectWeeks = $("#selectWeek").val();
            const datafilter = data.filter(d =>
                d.DATA_TYPE === "OEE" &&
                d.CL_TYPE === "Week" &&
                d.FISCAL_YEAR === selectedYear &&
                selectedQuarters.includes(d.FISCAL_QUARTER) &&
                selectMonths.includes(d.FISCAL_MONTH_NUM) &&
                selectWeeks.includes(d.FISCAL_WEEK)
            );
            
            //获取所有周次，按 01WK, 02WK 排序
            const weekSet = {};
            datafilter.forEach(d => weekSet[d.DATE] = true);
            const xAxisData = Object.keys(weekSet).sort((a, b) => {
                const aNum = parseInt(a.replace("WK", ""));
                const bNum = parseInt(b.replace("WK", ""));
                return aNum - bNum;
            });

            //初始化结构
            const groups = ["白班 AA", "白班 TEST", "晚班 AA", "晚班 TEST"];
            const groupMap = {};
            groups.forEach(g => groupMap[g] = []);

            //聚合每周每组 OEE
            xAxisData.forEach(week => {
                const rows = datafilter.filter(d => d.DATE === week);

                const temp = {
                    "白班 AA": [],
                    "白班 TEST": [],
                    "晚班 AA": [],
                    "晚班 TEST": []
                };

                rows.forEach(r => {
                    const key = `${r.WORK_CLASS} ${r.TYPE}`;
                    if (temp[key]) temp[key].push(r.OEE);
                });

                groups.forEach(g => {
                    const arr = temp[g];
                    const avg = arr.length ? arr.reduce((a, b) => a + b, 0) / arr.length : null;
                    groupMap[g].push(avg !== null ? +(avg * 100).toFixed(2) : null);
                });
            });

            //构建 series
            const seriesData = groups.map(name => ({
                name,
                type: "line",
                smooth: true,
                symbol: "circle",
                symbolSize: 6,
                data: groupMap[name]
            }));

            renderOeeLineChart(xAxisData, seriesData);

            //图表渲染
            function renderOeeLineChart(xAxisData, seriesData) {
                const chart = echarts.init(document.getElementById("chart9"));
                const option = {
                    title: {
                        text: "Weekly OEE",
                        left: "left",
                        textStyle: { fontSize: 12, fontWeight: "bold" }
                    },
                    tooltip: {
                        trigger: 'axis',
                        valueFormatter: function (value) {
                            return (value === null || value === undefined) ? '-' : value + '%';
                        }
                    },
                    legend: {
                        top: 20,
                        itemWidth: 10,
                        itemHeight: 10,
                        textStyle: { fontSize: 10 }
                    },
                    grid: { left: '1%', right: '1%', bottom: '1%', containLabel: true },
                    xAxis: {
                        type: "category",
                        data: xAxisData,
                        axisLabel: { fontSize: 10 }
                    },
                    yAxis: {
                        type: "value",
                        axisLabel: { formatter: "{value}%" }
                    },
                    series: seriesData
                };

                chart.setOption(option);
                window.addEventListener("resize", () => chart.resize());
            }
            weekOutputChart(datafilter);
        }

        //Week Output
        function weekOutputChart(data) {
            const summary = {};
            data.forEach(d => {
                if (!summary[d.DATE]) summary[d.DATE] = {};
                if (!summary[d.DATE][d.TYPE]) {
                    summary[d.DATE][d.TYPE] = { input: 0, output: 0 };
                }

                summary[d.DATE][d.TYPE].input += d.SUM_INPUT_QTY;
                summary[d.DATE][d.TYPE].output += d.SUM_OUTPUT_QTY;
            });
            const xAxis = Object.keys(summary).sort();
            const aaInput = xAxis.map(date => summary[date].AA?.input || 0);
            const aaOutput = xAxis.map(date => summary[date].AA?.output || 0);
            const aaYield = xAxis.map(date => {
                const d = summary[date].AA;
                return d && d.input > 0 ? +(d.output / d.input * 100).toFixed(1) : 0;
            });
            const testInput = xAxis.map(date => summary[date].TEST?.input || 0);
            const testOutput = xAxis.map(date => summary[date].TEST?.output || 0);
            const testYield = xAxis.map(date => {
                const d = summary[date].TEST;
                return d && d.input > 0 ? +(d.output / d.input * 100).toFixed(1) : 0;
            });
            const chart = echarts.init(document.getElementById('chart10'));
            chart.setOption({
                title: {
                    text: 'Weekly Output',
                    left: 'left',
                    textStyle: { fontSize: 12, fontWeight: 'bold' }
                },
                tooltip: {
                    trigger: 'axis',
                    formatter: params =>
                        params[0].axisValue + '<br/>' +
                        params.map(p =>
                            `${p.marker}${p.seriesName}: ` +
                            (p.value == null ? '-' : p.seriesName.includes('Yield') ? p.value + '%' : p.value)
                        ).join('<br/>')
                },
                legend: {
                    top: 20,
                    itemWidth: 10,
                    itemHeight: 10,
                    textStyle: { fontSize: 10 },
                    data: ['AA Input', 'AA Output', 'AA Yield', 'TEST Input', 'TEST Output', 'TEST Yield']
                },
                grid: { left: '1%', right: '1%', bottom: '1%', containLabel: true },
                xAxis: { type: 'category', data: xAxis,axisLabel: { fontSize: 10 }},
                yAxis: [
                  {
                    type: 'value',
                    alignTicks: true,
                    axisLabel: {
                      formatter: function (value) {
                        if (value >= 1000) {
                          return (value / 1000) + 'k';
                        }
                        return value;
                      }
                    }
                  },
                  {
                    type: 'value',
                    alignTicks: true,
                    axisLabel: {
                      formatter: '{value}%'
                    }
                  }
                ],
                series: [
                    { name: 'AA Input', type: 'bar', barGap: 0,barCategoryGap: "40%",data: aaInput },
                    { name: 'AA Output', type: 'bar', barGap: 0,barCategoryGap: "40%",data: aaOutput },
                    { name: 'AA Yield', type: 'line', yAxisIndex: 1, data: aaYield },
                    { name: 'TEST Input', type: 'bar', barGap: 0,barCategoryGap: "40%",data: testInput },
                    { name: 'TEST Output', type: 'bar', barGap: 0,barCategoryGap: "40%", data: testOutput },
                    { name: 'TEST Yield', type: 'line', yAxisIndex: 1, data: testYield }
                ]
            });
            window.addEventListener('resize', () => chart.resize());
        }

        //Week Downtime
        function weekDowntimeChart(data) {
            const selectedYear = $("#selectYear").val();
            const selectedQuarters = $("#selectQuarter").val();
            const selectMonths = $("#selectMonth").val();
            const selectWeeks = $("#selectWeek").val();
            const datafilter = data.filter(d =>
                d.DATA_TYPE === "EMS" &&
                d.CL_TYPE === "Week" &&
                d.FISCAL_YEAR === selectedYear &&
                selectedQuarters.includes(d.FISCAL_QUARTER) &&
                selectMonths.includes(d.FISCAL_MONTH_NUM) &&
                selectWeeks.includes(d.FISCAL_WEEK)
            );
            //周排序：01WK、02WK...
            const weekSet = {};
            datafilter.forEach(d => weekSet[d.FISCAL_WEEK] = true);
            const xAxisData = Object.keys(weekSet).sort((a, b) => {
                const aNum = parseInt(a.replace("WK", ""));
                const bNum = parseInt(b.replace("WK", ""));
                return aNum - bNum;
            });

            //数据结构
            const groups = ["白班 ASSY", "白班 TEST", "晚班 ASSY", "晚班 TEST"];
            const groupMap = {};
            groups.forEach(g => groupMap[g] = []);

            //每周聚合
            xAxisData.forEach(week => {
                const rows = datafilter.filter(d => d.FISCAL_WEEK === week);

                const temp = {
                    "白班 ASSY": [],
                    "白班 TEST": [],
                    "晚班 ASSY": [],
                    "晚班 TEST": []
                };

                rows.forEach(r => {
                    const key = `${r.WORK_CLASS} ${r.TYPE}`;
                    if (temp[key]) temp[key].push(r.DOWNTIME_RATE_PERCENT);
                });

                groups.forEach(g => {
                    const arr = temp[g];
                    const avg = arr.length ? arr.reduce((a, b) => a + b, 0) / arr.length : 0;
                    groupMap[g].push(+(avg * 100).toFixed(2));
                });
            });

            // 构建 series
            const seriesData = groups.map(name => ({
                name,
                type: 'bar',
                barGap: 0,
                barCategoryGap: "40%",
                data: groupMap[name]
            }));

            renderChart(xAxisData, seriesData);

            //渲染图表
            function renderChart(xAxisData, seriesData) {
                const chart = echarts.init(document.getElementById('chart11'));
                const option = {
                    title: {
                        text: 'Weekly Downtime',
                        left: 'left',
                        textStyle: { fontSize: 12, fontWeight: 'bold' }
                    },
                    tooltip: {
                        trigger: 'axis',
                        valueFormatter: function (value) {
                            return (value === null || value === undefined) ? '-' : value + '%';
                        }
                    },
                    legend: {
                        top: 20,
                        itemWidth: 10,
                        itemHeight: 10,
                        textStyle: { fontSize: 10 },
                        data: groups
                    },
                    grid: { left: '1%', right: '1%', bottom: '1%', containLabel: true },
                    xAxis: {
                        type: 'category',
                        data: xAxisData,
                        axisLabel: { fontSize: 10 }
                    },
                    yAxis: {
                        type: 'value',
                        axisLabel: { formatter: '{value}%' }
                    },
                    series: seriesData
                };

                chart.setOption(option);
                window.addEventListener('resize', () => chart.resize());
            }
        }

        //Week Assy
        function weekAssyChart(data) {
            const selectedYear = $("#selectYear").val();
            const selectedQuarters = $("#selectQuarter").val();
            const selectMonths = $("#selectMonth").val();
            const selectWeeks = $("#selectWeek").val();
            const selectReasons = $("#selectReason").val();
            const datafilter = data.filter(d =>
                d.DATA_TYPE === "EMS" &&
                d.CL_TYPE === "Week" &&
                d.FISCAL_YEAR === selectedYear &&
                selectedQuarters.includes(d.FISCAL_QUARTER) &&
                selectMonths.includes(d.FISCAL_MONTH_NUM) &&
                selectWeeks.includes(d.FISCAL_WEEK) &&
                selectReasons.includes(d.REASON)
            );
            //分组 TYPE + REASON
            const grouped = {};
            datafilter.forEach(item => {
                const { TYPE, REASON, DOWNTIME_RATE_PERCENT } = item;
                if (!grouped[REASON]) grouped[REASON] = { ASSY: [], TEST: [] };
                grouped[REASON][TYPE].push(DOWNTIME_RATE_PERCENT);
            });

            //平均值 + 汇总总值
            const reasonStats = Object.entries(grouped).map(([reason, types]) => {
                const assyAvg = types.ASSY.length ? types.ASSY.reduce((a, b) => a + b) / types.ASSY.length : 0;
                const testAvg = types.TEST.length ? types.TEST.reduce((a, b) => a + b) / types.TEST.length : 0;
                return {
                    reason,
                    assy: +(assyAvg * 100).toFixed(2),
                    test: +(testAvg * 100).toFixed(2),
                    total: +(assyAvg + testAvg) * 100
                };
            });

            //按 total 降序
            reasonStats.sort((a, b) => b.total - a.total);

            const xAxisData = reasonStats.map(r => r.reason);
            const assyData = reasonStats.map(r => r.assy);
            const testData = reasonStats.map(r => r.test);

            //累计百分比数据
            const cumulative = [];
            let sum = 0;
            const totalSum = reasonStats.reduce((acc, cur) => acc + cur.total, 0);
            reasonStats.forEach(r => {
                sum += r.total;
                cumulative.push(+(sum / totalSum * 100).toFixed(2));
            });
            const seriesData = [
                {
                    name: 'ASSY',
                    type: 'bar',
                    stack: 'total',
                    data: assyData
                },
                {
                    name: 'TEST',
                    type: 'bar',
                    stack: 'total',
                    data: testData
                },
                {
                    name: '累计百分比',
                    type: 'line',
                    yAxisIndex: 1,
                    smooth: true,
                    symbol: 'circle',
                    symbolSize: 6,
                    lineStyle: { color: 'orange' },
                    itemStyle: { color: 'orange' },
                    data: cumulative
                }
            ];

            //绘制图表
            function renderParetoChart(xAxisData, seriesData) {
                const chart = echarts.init(document.getElementById('chart12'));
                const option = {
                    title: {
                        text: 'Weekly Reason',
                        left: 'left',
                        textStyle: { fontSize: 12, fontWeight: 'bold' }
                    },
                    tooltip: {
                        trigger: 'axis',
                        valueFormatter: function (value) {
                            return (value === null || value === undefined) ? '-' : value + '%';
                        }
                    },
                    legend: {
                        top: 20,
                        itemWidth: 10,
                        itemHeight: 10,
                        textStyle: { fontSize: 10 },
                        data: ['ASSY', 'TEST', '累计百分比']
                    },
                    grid: { left: '1%', right: '1%', bottom: '1%', containLabel: true },
                    xAxis: {
                        type: 'category',
                        data: xAxisData,
                        axisLabel: {
                            rotate: 45,
                            fontSize: 10,
                            formatter: value => value.length > 10 ? value.slice(0, 10) + '…' : value
                        }
                    },
                    yAxis: [
                        {
                            type: 'value',
                            alignTicks: true,
                            axisLabel: { formatter: '{value}%' }
                        },
                        {
                            type: 'value',
                            alignTicks: true,
                            axisLabel: { formatter: '{value}%' }
                        }
                    ],
                    series: seriesData
                };
                chart.setOption(option);
                window.addEventListener('resize', () => chart.resize());
            }
            renderParetoChart(xAxisData, seriesData);
        }

        /*** Daily ***/
        //Daily OEE
        function dailyOeeChart(data) {
            const selectedYear = $("#selectYear").val();
            const selectedQuarters = $("#selectQuarter").val();
            const selectMonths = $("#selectMonth").val();
            const selectWeeks = $("#selectWeek").val();
            const datafilter = data.filter(d =>
                d.DATA_TYPE === "OEE" &&
                d.CL_TYPE === "Daily" &&
                d.FISCAL_YEAR === selectedYear &&
                selectedQuarters.includes(d.FISCAL_QUARTER) &&
                selectMonths.includes(d.FISCAL_MONTH_NUM) &&
                selectWeeks.includes(d.FISCAL_WEEK)
            );
            if (datafilter.length === 0) return;
            //标题汇总
            const sumInput = datafilter.reduce((a, b) => a + b.SUM_INPUT_QTY, 0);
            const sumOutput = datafilter.reduce((a, b) => a + b.SUM_OUTPUT_QTY, 0);
            const sumRunTime = datafilter.reduce((a, b) => a + b.SUM_RUN_TIME, 0);
            const sumDownTime = datafilter.reduce((a, b) => a + b.SUM_DOWN_TIME, 0);
            const avgUPH = datafilter.reduce((a, b) => a + b.UPH, 0) / datafilter.length;
            //计算公式
            const yieldRate = sumInput ? (sumOutput / sumInput) * 100 : 0;
            const timeAvailability = (sumRunTime + sumDownTime) ? (sumRunTime / (sumRunTime + sumDownTime)) * 100 : 0;
            const performanceRate = sumRunTime ? ((sumInput / (sumRunTime / 60)) / avgUPH) * 100 : 0;
            const oee = (yieldRate / 100) * (timeAvailability / 100) * (performanceRate / 100) * 100;
            //格式化
            const format = v => (v === 0 || isNaN(v)) ? "0.00%" : v.toFixed(2) + "%";
            //更新 KPI 面板
            $(".kpi.green .kpi-value").text(sumInput.toLocaleString());
            $(".kpi.orange .kpi-value").text(sumOutput.toLocaleString());
            $(".kpi.blue .kpi-value").text(format(yieldRate));
            $(".kpi.purple .kpi-value").text(format(timeAvailability));
            $(".kpi.yellow .kpi-value").text(format(performanceRate));
            $(".kpi.cyan .kpi-value").text(format(oee));

            //对日期排序
            const dateSet = {};
            datafilter.forEach(d => dateSet[d.DATE] = true);
            const xAxisData = Object.keys(dateSet).sort();  // 日期升序

            //初始化图例组（例如：白班 AA、白班 TEST 等）
            const groups = ["白班 AA", "白班 TEST", "晚班 AA", "晚班 TEST"];
            const groupMap = {};
            groups.forEach(g => groupMap[g] = []);

            //每日按组聚合
            xAxisData.forEach(date => {
                const rows = datafilter.filter(d => d.DATE === date);
                const temp = {
                    "白班 AA": null,
                    "白班 TEST": null,
                    "晚班 AA": null,
                    "晚班 TEST": null
                };

                rows.forEach(r => {
                    const key = `${r.WORK_CLASS} ${r.TYPE}`;
                    if (temp[key] === null) temp[key] = [];
                    temp[key].push(r.OEE);
                });

                groups.forEach(g => {
                    const values = temp[g];
                    const avg = values && values.length ? values.reduce((a, b) => a + b, 0) / values.length : null;
                    groupMap[g].push(avg !== null ? +(avg * 100).toFixed(2) : null);
                });
            });

            //构建折线系列
            const seriesData = groups.map(name => ({
                name,
                type: "line",
                smooth: true,
                symbol: "circle",
                symbolSize: 6,
                data: groupMap[name]
            }));

            renderDailyOeeChart(xAxisData, seriesData);

            //渲染图表
            function renderDailyOeeChart(xAxisData, seriesData) {
                const chart = echarts.init(document.getElementById('chart13'));
                const option = {
                    title: {
                        text: 'Daily OEE',
                        left: 'left',
                        textStyle: { fontSize: 12, fontWeight: 'bold' }
                    },
                    tooltip: {
                        trigger: 'axis',
                        valueFormatter: function (value) {
                            return (value === null || value === undefined) ? '-' : value + '%';
                        }
                    },
                    legend: {
                        top: 20,
                        itemWidth: 10,
                        itemHeight: 10,
                        textStyle: { fontSize: 10 },
                        data: groups
                    },
                    grid: { left: '1%', right: '1%', bottom: '1%', containLabel: true },
                    xAxis: {
                        type: 'category',
                        data: xAxisData,
                        axisLabel: { fontSize: 10, rotate: 45 }
                    },
                    yAxis: {
                        type: 'value',
                        axisLabel: { formatter: '{value}%' }
                    },
                    series: seriesData
                };
                chart.setOption(option);
                window.addEventListener('resize', () => chart.resize());
            }
            dailyOutputChart(datafilter);
        }

        //Daily Output
        function dailyOutputChart(data) {
            const summary = {};
            data.forEach(d => {
                if (!summary[d.DATE]) summary[d.DATE] = {};
                if (!summary[d.DATE][d.TYPE]) {
                    summary[d.DATE][d.TYPE] = { input: 0, output: 0 };
                }

                summary[d.DATE][d.TYPE].input += d.SUM_INPUT_QTY;
                summary[d.DATE][d.TYPE].output += d.SUM_OUTPUT_QTY;
            });
            const xAxis = Object.keys(summary).sort();
            const aaInput = xAxis.map(date => summary[date].AA?.input || 0);
            const aaOutput = xAxis.map(date => summary[date].AA?.output || 0);
            const aaYield = xAxis.map(date => {
                const d = summary[date].AA;
                return d && d.input > 0 ? +(d.output / d.input * 100).toFixed(1) : 0;
            });
            const testInput = xAxis.map(date => summary[date].TEST?.input || 0);
            const testOutput = xAxis.map(date => summary[date].TEST?.output || 0);
            const testYield = xAxis.map(date => {
                const d = summary[date].TEST;
                return d && d.input > 0 ? +(d.output / d.input * 100).toFixed(1) : 0;
            });
            const chart = echarts.init(document.getElementById('chart14'));
            chart.setOption({
                title: {
                    text: 'Daily Output',
                    left: 'left',
                    textStyle: { fontSize: 12, fontWeight: 'bold' }
                },
                tooltip: {
                    trigger: 'axis',
                    formatter: params =>
                        params[0].axisValue + '<br/>' +
                        params.map(p =>
                            `${p.marker}${p.seriesName}: ${p.value == null ? '-' : p.seriesName.includes('Yield') ? p.value + '%' : p.value}`
                        ).join('<br/>')
                },
                legend: {
                    top: 20,
                    itemWidth: 10,
                    itemHeight: 10,
                    textStyle: { fontSize: 10 },
                    data: ['AA Input', 'AA Output', 'AA Yield', 'TEST Input', 'TEST Output', 'TEST Yield']
                },
                grid: { left: '1%', right: '1%', bottom: '1%', containLabel: true },
                xAxis: { type: 'category', data: xAxis, axisLabel: { fontSize: 10, rotate: 45 }},
                yAxis: [
                  {
                      type: 'value',
                      alignTicks: true,
                      axisLabel: {
                      formatter: function (value) {
                        if (value >= 1000) {
                          return (value / 1000) + 'k';
                        }
                        return value;
                      }
                    }
                  },
                  {
                    type: 'value',
                    alignTicks: true,
                    axisLabel: {
                      formatter: '{value}%'
                    }
                  }
                ],
                series: [
                    { name: 'AA Input', type: 'bar', barGap: 0,barCategoryGap: "40%",data: aaInput },
                    { name: 'AA Output', type: 'bar', barGap: 0,barCategoryGap: "40%",data: aaOutput },
                    { name: 'AA Yield', type: 'line', yAxisIndex: 1, data: aaYield },
                    { name: 'TEST Input', type: 'bar', barGap: 0,barCategoryGap: "40%",data: testInput },
                    { name: 'TEST Output', type: 'bar', barGap: 0,barCategoryGap: "40%",data: testOutput },
                    { name: 'TEST Yield', type: 'line', yAxisIndex: 1, data: testYield }
                ]
            });
            window.addEventListener('resize', () => chart.resize());
        }
    </script>

    @*
    <script defer src="https://cdnjs.cloudflare.com/ajax/libs/dom-to-image-more/3.7.1/dom-to-image-more.min.js"></script>
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const btn = document.getElementById('save');
            btn.addEventListener('click', async () => {
                //1) 选单个元素：用 querySelector 或直接给一个 id
                const node = document.querySelector('.dashboard'); // 或 document.getElementById('capture')
                if (!node) { alert('未找到 .dashboard'); return; }
                //2) 高清导出：宽高 * 2 + scale(2)
                const scale = 2;
                try {
                    const dataUrl = await window.domtoimage.toPng(node, {
                        width: node.scrollWidth * scale,
                        height: node.scrollHeight * scale,
                        bgcolor: 'white',
                        style: {
                            transform: `scale(${scale})`,
                            transformOrigin: 'top left'
                        }
                    });
                    const a = document.createElement('a');
                    a.href = dataUrl;
                    a.download = 'screenshot.png';
                    a.click();
                } catch (err) {
                    console.error('截图失败:', err);
                    alert('截图失败：' + err.message);
                }
            });
        });
    </script>
    *@
</body>
</html>

